package com.ferry.common.util;

import com.ferry.common.util.concurrent.UnsafeUtil;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * Created by daiyong
 * 优化获取时间性能，copy from rocketmq
 */
public class SystemClock extends TimerOfPadding{

	private static final long NOW_VALUE_OFFSET = UnsafeUtil.objectFieldOffset(TimerOfPadding.class, "time");

	private final long precision;

	private SystemClock(long precision) {
		time = System.currentTimeMillis();
		this.precision = precision;
		scheduleClockUpdating();
	}

	private static final SystemClock millisClock = new SystemClock(1);

	public static SystemClock millisClock() {
		return millisClock;
	}

	private void scheduleClockUpdating() {
		ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(runnable -> {
			Thread t = new Thread(runnable, "system.clock");
			t.setDaemon(true);
			return t;
		});

		scheduler.scheduleAtFixedRate(() -> {
			/**
			 * 快速修改time的值，但是有代价 其他线程看不到修改的值
			 */
			if (NOW_VALUE_OFFSET > 0) {
				UnsafeUtil.getUnsafeAccessor()
						.getUnsafe()
						.putOrderedLong(SystemClock.this, NOW_VALUE_OFFSET, System.currentTimeMillis());
			} else {
				time = System.currentTimeMillis();
			}
		}, precision, precision, TimeUnit.MILLISECONDS);
	}

	public long time() {
		return time;
	}

	public long precision() {
		return precision;
	}

}

/**
 * 缓存行 防止伪共享 前后添加padding
 */
class TimerOfPadding {
	protected long p01, p02, p03, p04, p05, p06, p07;
	protected volatile long time;
	protected long p09, p10, p11, p12, p13, p14, p15;
}


